﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace FunctionGraph
{
    class SolutionEvaluatorVisitor : ExpressionVisitor<SolutionEvaluationNode>
    {
        public override SolutionEvaluationNode VisitConstant(ConstantNode constantNode)
        {
            return null;
        }

        public override SolutionEvaluationNode VisitVariable(VariableNode variableNode)
        {
            return null;
        }

        public override SolutionEvaluationNode VisitBinary(BinaryNode binaryNode)
        {
            if (binaryNode.Operator == MathOperator.Eql)
            {
                var rs = new ExprSolutionEvaluationNode();
                var subNode = new BinaryNode();
                subNode.Operator = MathOperator.Sub;
                subNode.Left = binaryNode.Left;
                subNode.Right = binaryNode.Right;
                rs.ExprExecutable = CodeGenerator.GenerateCode(subNode);
                return rs;
            }
            else if (binaryNode.Operator == MathOperator.Or || binaryNode.Operator == MathOperator.And)
            {
                var rs = new BinarySolutionEvaluationNode();
                rs.Operator = binaryNode.Operator;
                rs.Left = binaryNode.Left.Accept(this);
                rs.Right = binaryNode.Right.Accept(this);
            }
            return null;
        }

        public override SolutionEvaluationNode VisitUnary(UnaryNode unaryNode)
        {
            return null;
        }
    }

    class SolutionEvalTreeSerializer : ExpressionVisitor<object>
    {
        BinaryWriter writer;

        public SolutionEvalTreeSerializer(BinaryWriter writer)
        {
            this.writer = writer;
        }

        public override object VisitConstant(ConstantNode constantNode)
        {
            throw new NotImplementedException();
        }

        public override object VisitVariable(VariableNode variableNode)
        {
            throw new NotImplementedException();
        }

        public override object VisitBinary(BinaryNode binaryNode)
        {
            throw new NotImplementedException();
        }

        public override object VisitUnary(UnaryNode unaryNode)
        {
            throw new NotImplementedException();
        }

        public override object VisitBinarySolutionEval(BinarySolutionEvaluationNode node)
        {
            writer.Write(true);
            writer.Write((byte)node.Operator);
            node.Left.Accept(this);
            node.Right.Accept(this);
            return null;
        }

        public override object VisitExprSolutionEvaluationNode(ExprSolutionEvaluationNode node)
        {
            writer.Write(false);
            node.ExprExecutable.Serialize(writer);
            return null;
        }
    }
}
